package org.rcy.framework.utils.time;

import org.springframework.util.CollectionUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

public class TimeParam {

    public static final String DEFAULT_PATTERN = "yyyy-MM-dd";

    public static final String MONTH_PATTERN = "yyyy-MM";

    public Date startTime;

    public Date endTime;
    private ThreadLocal<SimpleDateFormat> MONTH_FORMAT_LOCAL = new ThreadLocal<>();

    public TimeParam(Date startTime, Date endTime) {
        this.startTime = startTime;
        this.endTime = endTime;
    }

    public TimeParam(){}

    private SimpleDateFormat getDateFormat() {
        SimpleDateFormat result = MONTH_FORMAT_LOCAL.get();
        if(result == null){
            result = new SimpleDateFormat(MONTH_PATTERN);
            MONTH_FORMAT_LOCAL.set(result);
        }
        return result;
    }

    public List<TimeParam> divideByMonth() {
        List<TimeParam> result = new ArrayList<>();
        String startMonth = curMonth(startTime);
        String endMonth = curMonth(endTime);
        if (startMonth.equals(endMonth)) {
            result.add(this);
            return result;
        }
        List<String> allMonth = dateToMonthFormat(startTime, endTime);
        if (CollectionUtils.isEmpty(allMonth)) {
            return result;
        }
        for (String monthFormat : allMonth) {
            result.add(monthToDate(monthFormat));
        }
        return result;
    }

    /**
     * 返回开始到结束之间所有天数的当天最大时间与当天最小时间
     * 例如 开始:1号  结束:2号 则返回
     * 1号0点0分0秒 与 1号23点59分59秒
     * 2号0点0分0秒 与 2号23点59分59秒
     * @param startTime
     * @param endTime
     * @return
     */
    public static List<TimeParam> divideByDay(Date startTime, Date endTime) {
        List<TimeParam> params = new ArrayList<>();
        ArrayList<Date> dates = new ArrayList<>();

        Calendar start = Calendar.getInstance();
        start.setTime(startTime);
        Calendar end = Calendar.getInstance();
        end.setTime(endTime);
        //需要用!after 而不能用before
        while(!start.after(end)) {
            dates.add(start.getTime());
            start.add(Calendar.DATE, + 1);
        }

        dates.forEach(date -> {
            Date endOfDay = TimeUtils.endOf(date);
            Date startOfDay = TimeUtils.startOf((date));
            TimeParam timeParam = new TimeParam(startOfDay, endOfDay);
            params.add(timeParam);
        });

        return params;
    }

    public  Date curMonth(String monthFormat) {
        try {
            return getDateFormat().parse(monthFormat);
        } catch (ParseException e) {
            return null;
        }
    }

    public TimeParam monthToDate(String month) {
        Date monthTime = curMonth(month);
        return new TimeParam(TimeUtils.startOfMonth(monthTime), TimeUtils.endOfMonth(monthTime));
    }

    private String curMonth(Date date) {
       return getDateFormat().format(date);
    }

    private List<String> dateToMonthFormat(Date startTime, Date endTime) {
        if (endTime == null) {
            endTime = new Date();
        }
        List<String> result = new ArrayList<>();
        result.add(getDateFormat().format(startTime));

        Calendar from = Calendar.getInstance();
        Calendar to = Calendar.getInstance();
        from.setTime(startTime);
        to.setTime(endTime);
        // 相差月份
        int minus = (to.get(Calendar.YEAR) - from.get(Calendar.YEAR)) * 12
                + (to.get(Calendar.MONTH) - from.get(Calendar.MONTH));
        for (int i=0; i<minus; i++) {
            from.set(Calendar.MONTH, from.get(Calendar.MONTH) + 1);
            result.add(getDateFormat().format(from.getTime()));
        }
        return result;
    }

    public Date getStartTime() {
        return startTime;
    }

    public void setStartTime(Date startTime) {
        this.startTime = startTime;
    }

    public Date getEndTime() {
        return endTime;
    }

    public void setEndTime(Date endTime) {
        this.endTime = endTime;
    }
}
